package com.biqee.service.bq.impl;

import java.util.List;

import org.apache.log4j.Logger;

import com.biqee.model.common.BqTuanStatus;
import com.biqee.model.db.BqTuan;
import com.biqee.model.db.TbItem;
import com.biqee.service.bq.BqEstimateResultService;
import com.biqee.service.bq.BqQueryRelationService;
import com.biqee.service.bq.BqTuanRankService;
import com.biqee.service.bq.BqTuanService;
import com.biqee.service.bq.EstimateItemService;
import com.biqee.service.bq.EstimateService;
import com.biqee.service.tb.TbItemService;

public class EstimateServiceImpl implements EstimateService {
	private static final Logger logger = Logger.getLogger(EstimateServiceImpl.class);
	
	private static final int DEFAULT_JOB_NUMBER = 100;
	
	@Override
	public void estimateAll() {
		boolean done = false;
		int start = 0;
		while(!done) {
			List<BqTuan> jobs = bqTuanService.listUnEstimatedTuans(start, DEFAULT_JOB_NUMBER);
			if(jobs.size() < DEFAULT_JOB_NUMBER) {
				done = true;
			}
			
			start += jobs.size();
			estimateJobs(jobs);
		}
	}

	@Override
	public void reEstimate(Integer bqTuanId) {
		logger.info("re estimate for tuanId: " + bqTuanId);
		
		BqTuan bqTuan = bqTuanService.getById(bqTuanId);
		if(bqTuan == null) {
			logger.error("no BqTuan matched for id: " + bqTuanId);
			return;
		}
		
		if(bqTuan.getTuanPrice() == null) {
			logger.error("null tuanprice! id: " + bqTuanId);
			return;
		}
		
		deleteOldEstimateResults(bqTuan);
		estimate(bqTuan);
		bqTuanService.tuanSummary(bqTuan.getId());
	}

	private void deleteOldEstimateResults(BqTuan bqTuan) {
		bqTuanService.updateStatus(BqTuanStatus.INIT, bqTuan.getId());
		bqEstimateResultService.deleteByBqTuanId(bqTuan.getId());
	}
	
	private void estimateJobs(List<BqTuan> bqTuans) {
		for(BqTuan bqTuan : bqTuans) {
			try {
				bqTuanService.search(bqTuan);
				deleteOldEstimateResults(bqTuan);
				estimate(bqTuan);	
			} catch (Exception ex) {
				logger.error("estimate failed. id: " + bqTuan.getId(), ex);
			}
			
		}
	}
	
	private void estimate(BqTuan bqTuan) {
		estimateAllRelatedItems(bqTuan);	
		bqTuanRankService.computeRanks(bqTuan);
		
	}
	
	private void estimateAllRelatedItems(BqTuan bqTuan) {
		if("y".equals(bqTuan.getIsExpire())) {
			logger.info("skip expired job. jobId: " + bqTuan.getId());
			return;			
		}
		
		if(bqTuan.getTuanPrice() == null) {
			logger.error("null tuanprice! id: " + bqTuan.getId());
			return;
		}
		
		// 读取聚划算活动商品
		Integer juTbItemId = bqQueryRelationService.getTbItemId(bqTuan.getId());
		if(juTbItemId == null) {
			logger.error("null juTbItemId! bqTuanId: " + bqTuan.getId());
			return;
		}
		
		TbItem juTbItem = tbItemService.read(juTbItemId);

		Integer bqTuanId = bqTuan.getId();
		List<Integer> tbItemIds = bqQueryRelationService.readAllTbItemIdsByBqTuanId(bqTuanId);
		for(Integer tbItemId : tbItemIds) {
			try {
				TbItem tbItem = tbItemService.read(tbItemId);
				estimateItemService.estimateItem(tbItem, juTbItem, bqTuan);
			} catch (Exception ex) {
				logger.error("estimate failed. tbItemId: " + tbItemId, ex);
			}
		}
	}
	
	private BqTuanService bqTuanService;

	public void setBqTuanService(BqTuanService bqTuanService) {
		this.bqTuanService = bqTuanService;
	}
	
	private BqQueryRelationService bqQueryRelationService;

	public void setBqQueryRelationService(
			BqQueryRelationService bqQueryRelationService) {
		this.bqQueryRelationService = bqQueryRelationService;
	}
	
	private TbItemService tbItemService;

	public void setTbItemService(TbItemService tbItemService) {
		this.tbItemService = tbItemService;
	}
	
	private EstimateItemService estimateItemService;

	public void setEstimateItemService(EstimateItemService estimateItemService) {
		this.estimateItemService = estimateItemService;
	}

	private BqTuanRankService bqTuanRankService;

	public void setBqTuanRankService(BqTuanRankService bqTuanRankService) {
		this.bqTuanRankService = bqTuanRankService;
	}
	
	private BqEstimateResultService bqEstimateResultService;

	public void setBqEstimateResultService(
			BqEstimateResultService bqEstimateResultService) {
		this.bqEstimateResultService = bqEstimateResultService;
	}
	
	
}
